package com.cman777.springc.idempotence.storage;

import com.cman777.springc.idempotence.ResultWrapper;
import com.cman777.springc.redis.annotation.RedisLock;
import lombok.extern.log4j.Log4j2;

import java.io.Serializable;
import java.util.function.Supplier;

/**
 * @author chenzhicong
 * @time 2020/9/15 10:41
 */
@Log4j2
public class CacheableStorage implements Storage {
    private Storage cacheStorage;
    private Storage persistenceStorage;

    public CacheableStorage(Storage cacheStorage, Storage persistenceStorage) {
        this.cacheStorage = cacheStorage;
        this.persistenceStorage = persistenceStorage;
    }

    @Override
    @RedisLock(fixedPrefix = "Idempoment_CacheableStorage_setIfAbsent",salt = "#key")
    public boolean setIfAbsent(String key, Supplier<ResultWrapper> supplier){
        if(this.exists(key)){
            return false;
        }else{
            return this.setIfAbsent(key,supplier.get());
        }
    }

    @Override
    public boolean setIfAbsent(String key, ResultWrapper resultWrapper) {
        boolean cacheHave = !cacheStorage.setIfAbsent(key,resultWrapper);
        if (cacheHave) {
            log.info("缓存中已存在幂等键={}", key);
            return false;
        } else {
            boolean success = persistenceStorage.setIfAbsent(key,resultWrapper);
            if (!success) {
                log.info("持久层中已存在幂等键={}", key);
            }
            return success;
        }
    }


    @Override
    public boolean delete(String idempotenceId) {
        try {
            cacheStorage.delete(idempotenceId);
            persistenceStorage.delete(idempotenceId);
            return true;
        } catch (Exception e) {
            log.info("删除幂等键异常");
            log.error(e.getMessage(), e);
            return false;
        }

    }

    @Override
    public <T extends Serializable> ResultWrapper<T> getResult(String idempotenceId) {
        ResultWrapper result = cacheStorage.getResult(idempotenceId);
        if(result == null){
            result =  persistenceStorage.getResult(idempotenceId);
            cacheStorage.setIfAbsent(idempotenceId,result);
        }
        return  result;
    }

    @Override
    public boolean exists(String key) {
        boolean isExists = cacheStorage.exists(key);
        if(!isExists){
            isExists = persistenceStorage.exists(key);
        }
        return isExists;
    }
}
